#pragma once
#include <vector>
#include <pthread.h>
#include<semaphore.h>

template<class T>
class RingQueuePC
{
public:
    RingQueuePC(int cap)
    :_v(cap), _producer_index(0), _consumer_index(0)
    {
        pthread_mutex_init(&_prodecur_mtx, nullptr);
        pthread_mutex_init(&_consumer_mtx, nullptr);
        sem_init(&_prodecur_sem, 0, cap);
        sem_init(&_consumer_sem, 0, 0);
    }

    ~RingQueuePC()
    {
        pthread_mutex_destroy(&_prodecur_mtx);
        pthread_mutex_destroy(&_consumer_mtx);
        sem_destroy(&_prodecur_sem);
        sem_destroy(&_consumer_sem);
    }

public:
    void Push(T& task)
    {
        sem_wait(&_prodecur_sem); // 获取信号量
        pthread_mutex_lock(&_prodecur_mtx);
        _v[_producer_index++] = task;
        _producer_index %= _v.size();
        pthread_mutex_unlock(&_prodecur_mtx);
        sem_post(&_consumer_sem); // 释放信号量
    }

    void Pop(T* task)
    {
        sem_wait(&_consumer_sem); // 获取信号量
        pthread_mutex_lock(&_consumer_mtx);
        *task = _v[_consumer_index++];
        _consumer_index %= _v.size();
        pthread_mutex_unlock(&_consumer_mtx);
        sem_post(&_prodecur_sem); // 释放信号量
    }

private:
    std::vector<T> _v; // 环形队列
    sem_t _prodecur_sem; // 信号量
    sem_t _consumer_sem; // 信号量
    pthread_mutex_t _prodecur_mtx;
    pthread_mutex_t _consumer_mtx;
    int _producer_index;
    int _consumer_index;
};
